/**
 * 创建data table 定义
 * @returns {{template: string, data(): {tableData: [{date: string, address: string, name: string},{date: string, address: string, name: string},{date: string, address: string, name: string},{date: string, address: string, name: string}]}}|{tableData: [{date: string, address: string, name: string},{date: string, address: string, name: string},{date: string, address: string, name: string},{date: string, address: string, name: string}]}}
 */
import {createDymFormWidgetDef} from "@/zform/cm-field-core";
import {getComputedFunFields} from "@/zform/hooks/common";

/**
 * 创建表格
 * @param properties
 * @param ctx
 * @param injectTable
 * @param tableAttrStr
 * @param tableConfig
 * @param parentKey
 * @param actions {[]}
 * @returns {{tableData: *[]}|{template: `
      <div>{{tableData}}
      <el-table
          :data="tableData"
          style="width: 100%">
        ${string}
      </el-table>
      <div>
        <el-button @click="appendItem">
          append
        </el-button>
      </div>
      </div>
    `, data(): {tableData: []}, provide(): {dataTableIns: {onInput(*, *): void}}, methods: {onChange(): void, append(): void}}|{dataTableIns: {onInput(*, *): void}}}
 */
export function buildDataTableDef(properties = {}, ctx, {tableAttrStr = '', tableConfig = {},  parentKey = '', injectTable = {}, actions = []} = {}) {
  let zformMeta  = globalThis.ZForm.getZFormMeta(ctx)
  let CustomDymComponent = zformMeta.CustomDymComponent

  // console.log(CustomDymComponent)
  let props = Object.entries(properties)
  // console.log(props)

  let map = new Map()
  props.forEach(([property, prop]) => {
    let allPaths = []
    // console.log(key, prop)
    if (prop.computedFun) {
      getComputedFunFields(prop.computedFun, allPaths)
    }
    map.set(allPaths, {
      prop,
      property
    })
  })

  function createDefaultObj(props) {
    let obj = {
      [UUID_KEY]: ZY.rid()
    }
    props.forEach(([propKey]) => {

      obj[propKey] = ''
    })
    return obj
  }

  let columns = props.map(([propKey, prop]) => {
    // console.log(propKey)
    let label = ZY.lodash.get(prop, 'ui.label')
    let widget = ZY.lodash.get(prop, 'ui.widget')
    let rules = ZY.lodash.get(prop, 'rules')

    let widgetName = widget + '__widget__' + ZY.rid(10).toLowerCase()
    // let cmFieldTpl = fieldMixin(prop)
    // console.log(cmFieldTpl, ctx)
    //
    // CustomDymComponent.registerOnce(
    //   createTemCmFieldCom()
    // )
    let widgetDef = createDymFormWidgetDef(widgetName, prop, {
      widgetUUID: ZY.rid()
    })
    widgetDef.inject = ['dataTableIns'];
    widgetDef.props = {
      scope: null,
      props: null
    }
    widgetDef.methods.zfield__onInput = function (newVal) {
      let widgetCtx = this
      // let formItem = widgetCtx.$el.parentElement
      // console.log('zfield__onInput', newVal, formItem, rules)

      function onSuccess() {
        // widgetCtx.dataTableIns.removeErrorMap(propKey)
        widgetCtx.dataTableIns.onInput(newVal, widgetCtx.scope)
        // formItem.classList.remove('is-table-form-error')
      }

      // if (rules) {
      //   const validator = new ZY_EXT.Schema({
      //     model: rules
      //   });
      //   validator.validate({ model: newVal}).then(() => {
      //     onSuccess()
      //   }).catch(({ errors, fields }) => {
      //     // console.log(errors, fields)
      //     // widgetCtx.dataTableIns.setErrorMap(propKey)
      //     // if (!formItem.classList.contains('is-table-form-error')) {
      //     //   formItem.classList.add('is-table-form-error')
      //     // }
      //   });
      // } else {
      //   onSuccess()
      // }

      onSuccess()


    }
    widgetDef.beforeMount = function () {

      let value = this.props.row[this.props.column.property]
      if (typeof value !== 'undefined') {
        this.value = value
      }
      // console.log(this)
    }
    // console.log(widgetDef)
    CustomDymComponent.registerOnce(widgetDef)

    return {
      tpl: `<el-table-column
          prop="${propKey}"
          label="${label}"
          ><template slot-scope="props"
          >
          <el-form-item :prop="'${parentKey}.' +props.$index + '.${propKey}' " :rules="getPropRules('${propKey}')" :id="'${propKey}__'+props.$index" >
         <${widgetName} 
          
          :ref="'${propKey}__'+props.$index"  
          :props="props" :scope="props"></${widgetName}> 
</el-form-item>
         </template></el-table-column>`
    }
  })
  // console.log(columns)

  let actionColoumnTpl = ''
  if (Array.isArray(actions) && actions.length > 0) {

    actionColoumnTpl = `
    <el-table-column label="操作">
    <template slot-scope="props">
   <el-button v-for="action in actions"
   v-bind="action.attrs"
   v-on="bindAction(action.on, {props, ctx: exportCtx})"
   >{{action.label}}</el-button>
</template>
</el-table-column>
    `
  }

  const UUID_KEY = 'ROW_UUID'

  /**
   * 计算
   * @param rowData
   * @param keys
   * @returns {number}
   */
  function countColumn(rowData, keys) {
    let ret = 0;
    ZY.lodash.each(rowData, function (item, key) {
      if (keys.includes(key)) {
        if (!Number.isNaN(Number(item))) {
          ret = Number(item) + ret
        }
      }
    })
    // console.log('countColumn', ret)
    return ret
  }

  let def = {
    template: `
      <div>
      <el-table
          :data="tableData"
      :row-key="rowKey"
          :summary-method="getSummaries"
          ${tableAttrStr}
      >
        ${columns.map(v => v.tpl).join()}
        ${actionColoumnTpl}
        <template slot="append">
          <component v-if="tableData && tableData.length > 0" :is="appendTableWidget"></component>
        </template>
      </el-table>
      <div>
        <el-button @click="appendItem">
          添加
        </el-button>
      </div>
      </div>
    `,
    data() {
      let self = this;
      return {
        tableData: [],
        actions,
        errorMap: {},
        exportCtx: {
          appendItem: self.appendItem,
          deleteItem: self.deleteItem,
        },
        appendTableWidget: ''
      }
    },
    mounted() {
      // console.log(this.$el)
      let self = this
      setTimeout(() => {
        let tableHeader = this.$el.querySelector('.el-table__header')
        let cellGroup = tableHeader.querySelector('colgroup').cloneNode(true)
        let appendTableWidget = ZY.rid()
        let com = {
          name: appendTableWidget,
          data() {
            return {}
          },
          template: `<table class="el-table__append">${cellGroup.outerHTML}
          <tbody>
<!--            <tr class="el-table__row">-->
<!--              <td class="el-table__cell">append1</td>-->
<!--              <td class="el-table__cell">append2</td>-->
<!--            </tr>-->
          </tbody>
          </table>`
        }
        CustomDymComponent.registerOnce(com)
        self.appendTableWidget = appendTableWidget
        // console.log(cellGroup)
      }, 30)
    },
    provide() {
      let self = this
      return {
        dataTableIns: {
          setErrorMap(propKey) {
            // self.errorMap[propKey] = 1
          },
          removeErrorMap(propKey) {
            // Reflect.deleteProperty(self.errorMap, propKey)
          },
          onInput(v, scope) {
            let column = scope.column
            let property = column.property
            ZCONSOLE.log(`[dataTable change] index: ${scope.$index} property: ${column.property}`, v)
            self.tableData[scope.$index][column.property] = v
            map.forEach(function (item, fieldKeys) {
              if (fieldKeys.includes(property)) {
                let count = countColumn(self.tableData[scope.$index], fieldKeys)
                // console.log('is ok', item, fieldKeys, self.$refs)
                let targetCtx = self.$refs[`${item.property}__` + scope.$index]
                if (targetCtx) {
                  // console.log(targetCtx)
                  targetCtx.zfield__setVal(count)
                }
                self.tableData[scope.$index][item.property] = count
              }
            })
            self.onChange()
          }
        }
      }
    },
    methods: {
      getPropRules(propKey, ) {
        let prop = new Map(props).get(propKey)
        // console.log(props, propKey, prop)
        return ZY.lodash.get(prop, 'rules', undefined)
      },
      getColumnCls(propKey) {
        let isError = this.errorMap[propKey]
        // console.log(isError)
        return {
          ['is-table-form-error']: isError
        }
      },
      getSummaries(param) {
        const { columns, data } = param;
        const sums = [];
        columns.forEach((column, index) => {
          if (index === 0) {
            sums[index] = '总价';
            return;
          }
          const values = data.map(item => Number(item[column.property]));
          if (!values.every(value => isNaN(value))) {
            sums[index] = values.reduce((prev, curr) => {
              const value = Number(curr);
              if (!isNaN(value)) {
                return prev + curr;
              } else {
                return prev;
              }
            }, 0);
            sums[index] += ' 元';
          } else {
            sums[index] = '';
          }
        });

        return sums;
      },
      bindAction(obj, binds) {
        let o = {}
        ZY.lodash.each(obj, function (item, key) {
          // console.log(o, item)
          o[key] = function (e) {
            item(binds, e)
          }
        })
        return o
      },
      rowKey(row) {
        // console.log('rowKey', row)
        if (row[UUID_KEY]) {
          return row[UUID_KEY]
        }
        return row
      },
      onChange() {
        let self = this
        let data = []
        self.tableData.forEach(item => {
          let v = JSON.parse(JSON.stringify(item))
          delete v[UUID_KEY]
          data.push(v)
        })
        if (injectTable && injectTable.onChange) {
          injectTable.onChange(data)
        }
      },
      appendItem() {
        this.tableData.push(createDefaultObj(props))
        this.$nextTick(() => {
          this.onChange()
        })
      },
      deleteItem(index) {
        this.tableData.splice(index, 1)
        this.$nextTick(() => {
          this.onChange()
        })
      },
      setValue(newVal) {
        // console.log(newVal)
        let self  = this
        if (Array.isArray(newVal)) {
          self.tableData = newVal.map(v => {
            v[UUID_KEY] = ZY.rid()
            return v
          })
        }
      }
    }
  }
  return def
}
